package no.rmz.chez.chess.pieces;

import java.util.Collection;

import no.rmz.chez.chess.board.ChessBoard;
import no.rmz.chez.chess.board.Color;
import no.rmz.chez.chess.board.Coord;
import no.rmz.chez.game.Move;

/**
 * Implementing a chess pawn.
 */
public final class Pawn extends ChessPiece {

    /**
     * Create a new pawn with a specific color.
     * @param c the color of the pawn
     */
    public Pawn(final Color c) {
        super(c, "Pawn", "P");
    }

    /**
     * When converting a pawn to a queen, get the  queen of
     * the appropriate color.
     * @return the queen
     */
    public ChessPiece getMyQueenPiece() {
        if (getColor() == Color.BLACK) {
            return ChessPiece.BQ;
        } else if (getColor() == Color.WHITE) {
            return ChessPiece.WQ;
        } else {
            throw new RuntimeException("Unknown piece color " + getColor());
        }
    }

    /**
     * Move a pawn from its source to its destination,
     * transforming it into a queen if appropriate.
     * @param source where the move is startring
     * @param destination where the move ends
     * @return a move
     */
    public Move pMove(final Coord source, final Coord destination) {
        assert (source      != null);
        assert (destination != null);
        final Move m = new Move(this, source, destination);
        if (isLastPossibleStep(destination)) {
            m.transformMovingPieceTo(getMyQueenPiece());
        }

        return m;
    }

    public final boolean isLastPossibleStep(Coord destination){
        int lastYCoord = Coord.MIN_BOARD_INDEX;
        if (getColor() == Color.WHITE) {
            lastYCoord = Coord.MAX_BOARD_INDEX;
        }
        return destination.getY() == lastYCoord;
    }

    /**
     * Figure out the positive direction of movement from
     * the color of the piece.
     * @return
     */
    private int getForwardDirection() {
        if (Color.WHITE == getColor()) {
            return 1;
        } else {
            return -1;
        }
    }

    /**
     * Figure out if this pawn has moved yet or not.
     * Return true iff it hasn�t.
     * @param c the coordinate where the pawn is located.
     * @return true iff the pawn is in its initial position.
     */
    public  boolean isInInitialPosition(final Coord c) {
        final int y = c.getY();
        if (getColor() == Color.BLACK) {
            return (y == 6);
        } else {
            return (y == 1);
        }
    }

    @Override
    public final void addMoves(
            final Collection<Move>  result,
            final ChessBoard        b,
            final Coord             source) {

        // Perform sanity checks in superclass.
        super.addMoves(result, b, source);

        // Figure out direction of movement and
        // length of non-capturing ray.
        final int forwardDirection = getForwardDirection();
        final int rayLength;
        if (isInInitialPosition(source)) {
            rayLength = 2;
        } else {
            rayLength = 1;
        }

        //  Generate non-capturing moves
        for (int dy = 1; dy <= rayLength; dy++) {
            final Coord target = source.add(0, forwardDirection * dy);
            if ((target != null) && b.coordIsFree(target)) {
                result.add(pMove(source, target));
            }
        }


        // Generate capturing moves
        for (int dx = -1; dx <= 1; dx += 2) {
            final Coord target = source.add(dx, forwardDirection);
            if (target != null) {
                final ChessPiece p = b.getPieceAt(target);
                if ((p != null) && (p.getColor() != getColor())) {
                    final Move m = pMove(source, target);
                    m.setCapturing(true);
                    result.add(m);
                }
            }
        }
    }
}